#pragma once

/*
 * A barely usable WeakCallback.
 */

#include <functional>
#include <memory>

namespace anet {
	namespace util {
		template<typename CLASS, typename... ARGS>
		class CWeakCallback {
		public:
			CWeakCallback(const std::weak_ptr<CLASS>& obj,
				const std::function<void(CLASS*, ARGS...)>& func)
				: m_object(obj), m_function(func) {
			}
			virtual ~CWeakCallback() = default;

		public:
			void operator()(ARGS&&... args) const {
				std::shared_ptr<CLASS> ptr(m_object.lock());
				if (ptr) {
					m_function(ptr.get(), std::forward<ARGS>(args)...);
				}
			}

		private:
			std::weak_ptr<CLASS> m_object;
			std::function<void(CLASS*, ARGS...)> m_function;
		};


		// CLASS's non-const member function.
		template<typename CLASS, typename... ARGS>
		CWeakCallback<CLASS, ARGS...> 
		makeWeakCallback(const std::shared_ptr<CLASS>& object, void (CLASS::*function)(ARGS...)) {
			return CWeakCallback<CLASS, ARGS...>(object, function);
		}

		// CLASS's const member function.
		template<typename CLASS, typename... ARGS>
		CWeakCallback<CLASS, ARGS...> 
		makeWeakCallback(const std::shared_ptr<CLASS>& object, void (CLASS::*function)(ARGS...) const) {
			return CWeakCallback<CLASS, ARGS...>(object, function);
		}
	} 
}